﻿using ITSparta.Collections;
using ITSparta.MVVM;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;

namespace SPConfigDBReaderApp.ViewModels
{
    public class ObjectViewModel : ViewModelBase
    {
        #region Fields

        private MTObservableCollection<ObjectViewModel> _childObjects = new MTObservableCollection<ObjectViewModel>();
        private bool _isSelected = false;
        private bool _isExpanded = false;
        private bool _isLoaded = false;
        private bool _isActivted = false;
        private string _xml = null;
        private bool _isXmlProcessed = false;

        private MTObservableCollection<ObjectsGroupViewModel> _objectGroups = new MTObservableCollection<ObjectsGroupViewModel>();

        #endregion

        #region Properties

        public Guid Id { get; private set; }
        public Guid ClassId { get; private set; }
        public Guid ParentId { get; private set; }
        public string Name { get; private set; }
        public string XML
        {
            get
            {
                if (!_isXmlProcessed)
                {
                    _isXmlProcessed = true;

                    var doc = new System.Xml.XmlDocument();
                    doc.LoadXml(_xml);

                    var sb = new System.Text.StringBuilder();
                    System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
                    {
                        Indent = true,
                        IndentChars = "  ",
                        NewLineChars = "\r\n",
                        NewLineHandling = System.Xml.NewLineHandling.Replace
                    };
                    using (var writer = System.Xml.XmlWriter.Create(sb, settings))
                    {
                        doc.Save(writer);
                    }

                    _xml = sb.ToString();
                }

                return _xml;
            }
        }

        public bool IsRoot { get { return Id == ParentId; } }
        public MTObservableCollection<ObjectViewModel> ChildObjects
        {
            get
            {
                return _isActivted ? _childObjects : null;
            }
        }
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value)
                {
                    _isActivted = true;
                    OnPropertyChanged("ChildObjects");

                    MainWindowViewModel.Current.SelectedObject = this;
                }
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
        public bool IsExpanded { get { return _isExpanded; } set { _isExpanded = value; OnPropertyChanged("IsExpanded"); } }
        public int Count { get { return _childObjects.Count; } }
        public ClassViewModel Class { get; private set; }
        public ObjectViewModel Parent { get; private set; }
        public MTObservableCollection<ObjectsGroupViewModel> ObjectGroups { get { return _objectGroups; } }

        #endregion

        #region Constructor

        internal ObjectViewModel(SqlDataReader reader)
        {
            Id = (Guid)reader["Id"];
            ClassId = (Guid)reader["ClassId"];
            ParentId = (Guid)reader["ParentId"];
            Name = (string)reader["Name"];
            _xml = (string)reader["Properties"];

            ClassViewModel c = null;
            if (!MainWindowViewModel.Current.TryGetClass(ClassId, out c))
                throw new Exception();
            Class = c;

            Class.Objects.Add(this);

            if (IsRoot)
                _isActivted = true;
        }

        #endregion

        #region Methods

        internal void Init()
        {
            if (_isLoaded)
                return;
            _isLoaded = true;

            var temp = new List<ObjectViewModel>();
            foreach (var c in MainWindowViewModel.Current.Objects)
            {
                if (c.ParentId != Id || c.IsRoot)
                    continue;

                temp.Add(c);

                c.Parent = this;
            }

            foreach (var c in temp.OrderBy(it => it.Class.ClassName).OrderBy(it => it.Name))
                _childObjects.Add(c);

            var dics = new Dictionary<Guid, ObjectsGroupViewModel>();
            foreach (var o in _childObjects)
            {
                ObjectsGroupViewModel g = null;
                if (!dics.TryGetValue(o.ClassId, out g))
                    dics.Add(o.ClassId, g = new ObjectsGroupViewModel(this, o.Class));
                g.Objects.Add(o);
            }

            foreach (var g in dics.Values)
                _objectGroups.Add(g);
        }

        #endregion
    }
}